// ml:run = $bin < input
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>

using ll = long long;

struct edge { ll from, to, cost, id; };

ll const inf = (1ll) << 44;
int const maxn = 2000;
ll n, m, len, start, end;
std::vector<edge> edges;
ll from[maxn];
ll from_node[maxn];

std::vector<std::vector<edge>> graph;

void add_edge(ll u, ll v, ll cost, ll id)
{
    graph[u].push_back({u, v, cost, id});
    graph[v].push_back({v, u, cost, id});
}

ll dijkstra(ll source, ll target)
{
	ll num = n + 4; // tot vertices FIXME
	ll dist[num];
	std::fill(dist, dist + num, inf);
	dist[source] = 0;
	typedef std::pair<ll, ll> cost_end;
	std::priority_queue<cost_end, std::vector<cost_end>, std::greater<cost_end> > pq;
	pq.push(std::make_pair(0, source));
    from_node[source] = source;
	while (!pq.empty()) {
		cost_end tmp = pq.top(); pq.pop();
		ll u = tmp.second;
		if (dist[u] < tmp.first) continue;

		for (auto edge : graph[u]) {
			ll v = edge.to, c = edge.cost;
			if (dist[v] > dist[u] + c) {
				dist[v] = dist[u] + c;
                from[v] = edge.id;
                from_node[v] = u;
				pq.push(std::make_pair(dist[v], v));
			}
		}
	}
	return dist[target];
}

int main()
{
    std::ios_base::sync_with_stdio(false);
    std::cin >> n >> m >> len >> start >> end;
    graph.resize(n + 1);
    edges.resize(m);
    for (ll i = 0; i < m; i++) {
        std::cin >> edges[i].from >> edges[i].to >> edges[i].cost;
        edges[i].id = i;
        if (edges[i].cost)
            add_edge(edges[i].from, edges[i].to, edges[i].cost, i);
    }
    ll sp1 = dijkstra(start, end);
    if (sp1 < len) { std::cout << "NO\n"; return 0; }

    /* graph.clear(); */
    /* graph.resize(n + 1); */
    /* for (int i = 0; i < m; i++) { */
    /*     auto e = edges[i]; */
    /*     add_edge(e.from, e.to, e.cost, i); */
    /* } */
    /* ll sp2 = dijkstra(start, end); */
    /* if (sp2 > len) { std::cout << "NO\n"; return 0; } */

    graph.clear();
    graph.resize(n + 1);
    for (int i = 0; i < m; i++) {
        auto e = edges[i];
        add_edge(e.from, e.to, e.cost ? e.cost : 1, i);
    }
    ll sp3 = dijkstra(start, end);
    if (sp3 > len) { std::cout << "NO\n"; return 0; }

    /* std::cerr << ":: " << sp1 << " " << sp2 << " " << sp3 << "\n"; */

    /* ll del = len - sp3; */
    /* ll count = sp3 - sp2; */
    /* if ((!count && len) || (count > del)) { */
    /*     std::cout << "NO\n"; */
    /*     return 0; */
    /* } */

    int now = end;
    int count = 0;
    ll large = len - sp3 + 1;
    while (now != start) {
        if (!edges[from[now]].cost) count++;
        now = from_node[now];
    }
    now = end;
    if (!count && sp3 != len) {
        std::cout << "NO\n";
        return 0;
    }
    while (now != start) {
        if (!edges[from[now]].cost) {
            if (count > 1) edges[from[now]].cost = 1;
            else edges[from[now]].cost = large;
            count--;
        }
        now = from_node[now];
    }
    for (auto & e : edges)
        if (!e.cost) e.cost = len;
    std::cout << "YES\n";
    for (auto e : edges) {
        std::cout << e.from << " " << e.to << " " << e.cost << "\n";
    }
}

